package com.leezai.mqtt.config;

import com.leezai.mqtt.dto.TopicConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.yaml.snakeyaml.Yaml;

import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * MQTT配置属性类
 * 不依赖Spring容器管理，通过YAML文件加载配置
 */
public class Properties {

    private static final Logger log = LoggerFactory.getLogger(Properties.class);

    // 默认配置值
    private String url = "tcp://localhost:1883";
    private String username;
    private String password;
    private List<TopicConfig> topics = new ArrayList<>();
    private String clientIdPrefix;

    // topic配置映射，便于快速查找
    private Map<String, TopicConfig> topicConfigMap = new ConcurrentHashMap<>();

    // 单例实例
    private static volatile Properties instance;
    private static volatile boolean initialized = false;

    // 私有构造函数
    private Properties() {}

    /**
     * 获取单例实例
     */
    public static Properties getInstance() {
        if (instance == null) {
            synchronized (Properties.class) {
                if (instance == null) {
                    instance = new Properties();

                }
            }
        }
        return instance;
    }

    /**
     * 初始化配置（在应用启动时调用）
     */
    public static synchronized void initialize() {
        if (initialized) {
            return;
        }
        try {
            Properties instance = getInstance();
            instance.loadFromYaml();
            initialized = true;
        } catch (Exception e) {
            log.error("Failed to initialize Properties: " + e.getMessage(), e);
        }
    }

    /**
     * 从YAML文件加载配置
     */
    @SuppressWarnings("unchecked")
    private void loadFromYaml() {
        try {
            // 获取环境变量或系统属性指定的配置文件后缀
            String profile = getActiveProfile();
            List<InputStream> configStreams = getConfigResources(profile);

            // 按优先级加载配置文件
            boolean loaded = false;
            for (InputStream inputStream : configStreams) {
                if (inputStream != null) {
                    loadYamlFromStream(inputStream);
                    loaded = true;
                    break; // 找到第一个存在的配置文件就停止
                }
            }

            // 如果没有找到配置文件，尝试默认配置文件
            if (!loaded) {
                try (InputStream defaultStream = Thread.currentThread()
                        .getContextClassLoader()
                        .getResourceAsStream("application.yml")) {
                    if (defaultStream != null) {
                        loadYamlFromStream(defaultStream);
                        loaded = true;
                    }
                }
            }

            if (!loaded) {
                log.warn("No configuration file found, using default configuration");
            }

        } catch (Exception e) {
            log.error("Error loading YAML configuration: " + e.getMessage(), e);
        }
    }

    /**
     * 获取当前激活的配置文件后缀
     */
    private static String getActiveProfile() {
        // 优先级1: 系统属性
        String profile = System.getProperty("spring.profiles.active");
        if (profile != null && !profile.isEmpty()) {
            return profile;
        }

        // 优先级2: 环境变量
        profile = System.getenv("SPRING_PROFILES_ACTIVE");
        if (profile != null && !profile.isEmpty()) {
            return profile;
        }

        return null; // 没有指定profile
    }

    /**
     * 根据profile获取配置文件流列表（按优先级排序）
     */
    private static List<InputStream> getConfigResources(String profile) {
        List<InputStream> streams = new ArrayList<>();

        if (profile != null && !profile.isEmpty()) {
            // 根据逗号分隔的多个profile
            String[] profiles = profile.split(",");
            for (String p : profiles) {
                p = p.trim();
                if (!p.isEmpty()) {
                    // application-{profile}.yml
                    InputStream stream1 = Thread.currentThread()
                            .getContextClassLoader()
                            .getResourceAsStream("application-" + p + ".yml");
                    if (stream1 != null) streams.add(stream1);

                    InputStream stream2 = Thread.currentThread()
                            .getContextClassLoader()
                            .getResourceAsStream("application-" + p + ".yaml");
                    if (stream2 != null) streams.add(stream2);
                }
            }
        }

        // 添加默认配置文件
        InputStream defaultYml = Thread.currentThread()
                .getContextClassLoader()
                .getResourceAsStream("application.yml");
        if (defaultYml != null) streams.add(defaultYml);

        InputStream defaultYaml = Thread.currentThread()
                .getContextClassLoader()
                .getResourceAsStream("application.yaml");
        if (defaultYaml != null) streams.add(defaultYaml);

        return streams;
    }

    /**
     * 从指定输入流加载YAML配置
     */
    @SuppressWarnings("unchecked")
    private void loadYamlFromStream(InputStream inputStream) throws IOException {
        try {
            Yaml yaml = new Yaml();
            Map<String, Object> yamlData = yaml.load(inputStream);

            if (yamlData != null) {
                // 解析配置结构: mqtt.broker
                Map<String, Object> mqttConfig = (Map<String, Object>) yamlData.get("mqtt");
                if (mqttConfig != null) {
                    Map<String, Object> brokerConfig = (Map<String, Object>) mqttConfig.get("broker");
                    if (brokerConfig != null) {
                        // 设置基础属性
                        if (brokerConfig.containsKey("url")) {
                            this.url = (String) brokerConfig.get("url");
                        }
                        if (brokerConfig.containsKey("username")) {
                            this.username = (String) brokerConfig.get("username");
                        }
                        if (brokerConfig.containsKey("password")) {
                            this.password = (String) brokerConfig.get("password");
                        }
                        if (brokerConfig.containsKey("client-id-prefix")) {
                            this.clientIdPrefix = (String) brokerConfig.get("client-id-prefix");
                        }

                        // 设置topics
                        if (brokerConfig.containsKey("topics")) {
                            List<Map<String, Object>> topicsData =
                                    (List<Map<String, Object>>) brokerConfig.get("topics");
                            if (topicsData != null) {
                                List<TopicConfig> topicConfigs = new ArrayList<>();
                                for (Map<String, Object> topicData : topicsData) {
                                    TopicConfig topicConfig = new TopicConfig();
                                    if (topicData.containsKey("topic")) {
                                        topicConfig.setTopic((String) topicData.get("topic"));
                                    }
                                    if (topicData.containsKey("qos")) {
                                        topicConfig.setQos((Integer) topicData.get("qos"));
                                    }
                                    if (topicData.containsKey("type")) {
                                        topicConfig.setType((String) topicData.get("type"));
                                    }
                                    topicConfigs.add(topicConfig);
                                }
                                setTopics(topicConfigs);
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error("Error parsing YAML configuration: " + e.getMessage(), e);
            throw e;
        }
    }

    // Getters and Setters
    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public List<TopicConfig> getTopics() {
        return new ArrayList<>(topics);
    }

    public void setTopics(List<TopicConfig> topics) {
        this.topics = topics != null ? new ArrayList<>(topics) : new ArrayList<>();
        updateTopicConfigMap();
    }

    public String getClientIdPrefix() {
        return clientIdPrefix;
    }

    public void setClientIdPrefix(String clientIdPrefix) {
        this.clientIdPrefix = clientIdPrefix;
    }

    public Map<String, TopicConfig> getTopicConfigMap() {
        return new ConcurrentHashMap<>(topicConfigMap);
    }

    public TopicConfig getTopicConfig(String topic) {
        return topicConfigMap.get(topic);
    }

    /**
     * 更新topic配置映射
     */
    private void updateTopicConfigMap() {
        topicConfigMap.clear();
        if (topics != null && !topics.isEmpty()) {
            for (TopicConfig topicConfig : topics) {
                if (topicConfig != null && topicConfig.getTopic() != null) {
                    topicConfigMap.put(topicConfig.getTopic(), topicConfig);
                }
            }
        }
    }

    /**
     * 检查是否已初始化
     */
    public static boolean isInitialized() {
        return initialized;
    }

    /**
     * 手动设置所有属性
     */
    public static void setConfiguration(String url, String username, String password,
                                        List<TopicConfig> topics, String clientIdPrefix) {
        Properties instance = getInstance();
        instance.url = url != null ? url : instance.url;
        instance.username = username;
        instance.password = password;
        instance.clientIdPrefix = clientIdPrefix;
        instance.setTopics(topics);
        initialized = true;
    }
}
